
local Element = _ENV.import("./Element.lua");

local Frame = commonlib.inherit(Element);

Frame:Property("XmlPath");     -- xml文件路径

-- 构造函数
function Frame:ctor()
    self:SetClassName("Frame");    -- 元素名

    self.m_frame_class_map = {};   -- 元素集
    self.m_env = nil;              -- 环境
end

-- 初始化
function Frame:Init(xmlnode, parent)
    Frame._super.Init(self, xmlnode, parent);

    -- 加载页面
    self:Load(xmlnode);

    -- 扩展G
    self:ExtendG();

    return self;
end

-- 加载页面
function Frame:Load(xmlnode)
    local template = self:GetAttrStringValue("template");
    local url = self:GetAttrStringValue("url");

    xmlnode.external_childrens = {};
    xmlnode.internal_childrens = {};

    -- 属性为空 则从类数据中取
    if (template == "" and url == "") then url = self:GetXmlPath() or "" end
    -- 加载 xml 文件 获取模板内容
    if (template == "" and url ~= "") then template = commonlib.GetFileText(url) or "" end
    -- 内容为空则直接返回
    if (template == "") then return end

    -- 维持脚本和样式原本格式
    template = string.gsub(template, "[\r\n]<script(.-)>(.-)[\r\n]</script>", "<script%1>\n<![CDATA[\n%2\n]]>\n</script>");
    template = string.gsub(template, "[\r\n]<style(.-)>(.-)[\r\n]</style>", "<style%1>\n<![CDATA[\n%2\n]]>\n</style>");

    -- 解析模板为xml节点
    local children_xmlnodes = commonlib.FromXmlString(template);

    -- 加载子节点
    for _, children_xmlnode in ipairs(children_xmlnodes) do
        if (children_xmlnode.name == "style") then
            self:LoadStyleSheet(children_xmlnode);
        elseif (children_xmlnode.name == "script") then
            self:LoadScript(children_xmlnode);
        else
            local children_element = self:CreateElement(children_xmlnode);
            if (children_element) then self:AddChildren(children_element:Init(children_xmlnode, self)) end
        end
    end
end

-- 获取监控对象
function Frame:GetWatchObject()
    if (self.m_watch_object) then return self.m_watch_object end
    local parent_watch_object = Frame._super.GetWatchObject(self);
    self.m_watch_object = parent_watch_object and parent_watch_object:NewInheritWatchObject();
    return self.m_watch_object;
end

-- 获取脚本环境
function Frame:ExtendG()
    local G = self:GetG();

    -- 扩展全局函数
    G.RegisterFrameElement = function(tagname, filename)
        self:RegisterFrameElement(tagname, filename);
    end
end

-- 注册框架元素
function Frame:RegisterFrameElement(tagname, filename)
    if (type(filename) ~= "string") then return end
    local FrameClass = commonlib.inherit(Frame);
    FrameClass:SetXmlPath(filename);
    self.m_frame_class_map[string.lower(tagname)] = FrameClass;
end

-- 创建元素
function Frame:CreateElement(xmlnode)
    local tagname = string.lower(xmlnode.name or "");
    local FrameClass = self.m_frame_class_map[tagname];
    return FrameClass and FrameClass:new() or Frame._super.CreateElement(self, xmlnode);
end

return Frame;